home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / dev / lang / pcq12src.lzh / Source / Evaluate.p < prev    next >
Text File  |  1991-04-18  |  51KB  |  2,004 lines

  1. External;
  2.  
  3. {$I "Pascal.i"}
  4.  
  5.     Function GetLabel : Integer;
  6.         external;
  7.     Function GetFramePointer(Ref : Integer) : Regs;
  8.         External;
  9.     Function BaseType(b : TypePtr): TypePtr;
  10.         external;
  11.     Function SimpleType(t : TypePtr) : Boolean;
  12.         external;
  13.     Function NumberType(t : TypePtr) : Boolean;
  14.         External;
  15.     Function TypeCheck(l, r : TypePtr) : Boolean;
  16.         External;
  17.     Function ExpressionTree : ExprPtr;
  18.         External;
  19.     Procedure Optimize(Expr : ExprPtr);
  20.         External;
  21.     Procedure Error(msg : String);
  22.         External;
  23.     Function GetReference : ExprPtr;
  24.         External;
  25.     Function Match(s : Symbols) : Boolean;
  26.         External;
  27.     Function PromoteTypeA(Expr : ExprPtr; TP : TypePtr) : ExprPtr;
  28.         External;
  29.     Function MakeNode(s : Symbols; L, R : ExprPtr; TP : TypePtr;
  30.                 Val : Integer) : ExprPtr;
  31.         External;
  32.     Procedure PopStackSpace(Amount : Integer);
  33.          External;
  34.     Procedure Out_Operation0(op : OpCodes);
  35.         External;
  36.     Procedure Out_Operation1(op : OpCodes; Size : Byte;
  37.                     EA : EAModes; Reg : Regs);
  38.         External;
  39.     Procedure Out_Operation2(op : OpCodes; Size : Byte;
  40.                     SrcEA : EAModes; SrcReg : Regs;
  41.                     DestEA : EAModes; DestReg : Regs);
  42.         External;
  43.     Procedure Out_Extension(Ext : Integer);
  44.         External;
  45.  
  46.  
  47.  
  48. Function RegisterInUse(reg : Regs) : Boolean;
  49. begin
  50.     RegisterInUse := (UsedRegs and (1 shl Ord(reg))) <> 0;
  51. end;
  52.  
  53. Procedure MarkRegister(reg : Regs);
  54. begin
  55. {    if not RegisterInUse(reg) then
  56.         Writeln(OutFile, '*  ', RN[reg], ': used'); }
  57.     UsedRegs := UsedRegs or (1 shl Ord(reg));
  58. end;
  59.  
  60. Procedure UnmarkRegister(reg : Regs);
  61. begin
  62. {    if RegisterInUse(reg) then
  63.         Writeln(OutFile, '*  ', RN[reg], ': free'); }
  64.     UsedRegs := UsedRegs and (not (1 shl Ord(reg)));
  65. end;
  66.  
  67. Procedure SaveRegisterToStack(reg : Regs);
  68. begin
  69.     Out_Operation1(op_PUSH,4,ea_Register,reg);
  70.     StackLoad := StackLoad + 4;
  71.     UnmarkRegister(reg);
  72. end;
  73.  
  74. Procedure RestoreRegisterFromStack(reg : Regs);
  75. begin
  76.     Out_Operation1(op_POP,4,ea_Register,reg);
  77.     StackLoad := StackLoad - 4;
  78.     MarkRegister(reg);
  79. end;
  80.  
  81. Procedure FreeAllRegisters;
  82. begin
  83.     UsedRegs := 0;
  84.     NextDataRegister := d7;
  85.     NextAddressRegister := a3;
  86. end;
  87.  
  88. Procedure AllocateDataRegister(var reg : Regs; var Stacked : Boolean);
  89. begin
  90.     if NextDataRegister >= d2 then begin
  91.     reg := NextDataRegister;
  92.     Stacked := False;
  93.     Dec(NextDataRegister);
  94.     end else begin
  95.     SaveRegisterToStack(d7);
  96.     reg := d7;
  97.     Stacked := True;
  98.     end;
  99. end;
  100.  
  101. Procedure DeallocateDataRegister(reg : Regs; Stacked : Boolean);
  102. begin
  103.     if Stacked then
  104.     RestoreRegisterFromStack(reg)
  105.     else begin
  106.     UnmarkRegister(reg);
  107.     Inc(NextDataRegister);
  108.     end;
  109. end;
  110.  
  111. Procedure AllocateAddressRegister(var reg : Regs; var Stacked : Boolean);
  112. begin
  113.     if NextAddressRegister >= a0 then begin
  114.     reg := NextAddressRegister;
  115.     Stacked := False;
  116.     Dec(NextAddressRegister);
  117.     end else begin
  118.     SaveRegisterToStack(a3);
  119.     reg := a3;
  120.     Stacked := True;
  121.     end;
  122. end;
  123.  
  124.  
  125. Procedure DeallocateAddressRegister(reg : Regs; Stacked : Boolean);
  126. begin
  127.     if Stacked then
  128.     RestoreRegisterFromStack(reg)
  129.     else begin
  130.     UnmarkRegister(reg);
  131.     Inc(NextAddressRegister);
  132.     end;
  133. end;
  134.  
  135. Function TemporaryData : Regs;
  136. var
  137.     reg : Regs;
  138. begin
  139.     if not RegisterInUse(d0) then
  140.     TemporaryData := d0;
  141.     if not RegisterInUse(d1) then
  142.     TemporaryData := d1;
  143.     for reg := d7 to d2 do begin
  144.     if not RegisterInUse(reg) then
  145.         TemporaryData := reg;
  146.     end;
  147.     TemporaryData := a7;
  148. end;
  149.  
  150. Function TemporaryAddress : Regs;
  151. var
  152.     reg : Regs;
  153. begin
  154.     for reg := a0 to a3 do begin
  155.     if not RegisterInUse(reg) then
  156.         TemporaryAddress := reg;
  157.     end;
  158.     TemporaryAddress := a7;
  159. end;
  160.  
  161.  
  162. Procedure SaveAllRegisters;
  163. var
  164.     reg : Regs;
  165. begin
  166.     if (UsedRegs and $0FFF) <> 0 then begin
  167.     Out_Operation2(op_MOVEM,4,ea_RegList,a7,ea_PreDec,a7);
  168.     Out_Extension(UsedRegs and $0FFF);
  169.  
  170.     for reg := d0 to a3 do begin
  171.         if RegisterInUse(reg) then begin
  172.         UnmarkRegister(reg);
  173.         StackLoad := StackLoad + 4;
  174.         end;
  175.     end;
  176.     end;
  177. end;
  178.  
  179.  
  180. Procedure RestoreAllRegisters;
  181. var
  182.     reg : Regs;
  183. begin
  184.     if (UsedRegs and $0FFF) <> 0 then begin
  185.     Out_Operation2(op_MOVEM,4,ea_PostInc,a7,ea_RegList,a7);
  186.     Out_Extension(UsedRegs and $0FFF);
  187.  
  188.     for reg := d0 to a3 do begin
  189.         if RegisterInUse(reg) then
  190.         StackLoad := StackLoad - 4;
  191.     end;
  192.     end;
  193. end;
  194.  
  195.  
  196. Procedure SaveScratchRegisters;
  197.  
  198.     Procedure DoReg(reg : Regs);
  199.     begin
  200.     if RegisterInUse(reg) then begin
  201.         StackLoad := StackLoad + 4;
  202.         UnmarkRegister(reg);
  203.     end;
  204.     end;
  205.  
  206. begin
  207.     if (UsedRegs and $0303) <> 0 then begin
  208.     Out_Operation2(op_MOVEM,4,ea_RegList,a7,ea_PreDec,a7);
  209.     Out_Extension(UsedRegs and $0303);  { d0, d1, a0 and a1 }
  210.     DoReg(d0);
  211.     DoReg(d1);
  212.     DoReg(a0);
  213.     DoReg(a1);
  214.     end;
  215. end;
  216.  
  217.  
  218. Procedure RestoreScratchRegisters;
  219. var
  220.     WroteAny : Boolean;
  221.  
  222.     Procedure DoReg(reg : Regs);
  223.     begin
  224.     if RegisterInUse(reg) then
  225.         StackLoad := StackLoad - 4;
  226.     end;
  227.  
  228. begin
  229.     if (UsedRegs and $0303) <> 0 then begin
  230.     Out_Operation2(op_MOVEM,4,ea_PostInc,a7,ea_RegList,a7);
  231.     Out_Extension(UsedRegs and $0303); { d0, d1, a0 and a1 }
  232.  
  233.     DoReg(d0);
  234.     DoReg(d1);
  235.     DoReg(a0);
  236.     DoReg(a1);
  237.     end;
  238. end;
  239.  
  240.  
  241. {
  242.     This routine is used to add a constant value to any register.
  243.     It does so in the most efficient way, to wit:
  244.  
  245.     Add  0 < x <= 8 to An    : addq.w #x,An
  246.     Add word to An        : lea word(An),An
  247.     Add  9 <= x <= 16 to An    : addq.w #8,An
  248.                   addq.w #x-8,An
  249.  
  250.     Subtractions work the same way.  For data registers, A68k will
  251.     handle optimizations, so they just work normally.
  252. }
  253.  
  254. Procedure AddConstant(Amount : Integer; ToReg : Regs; Size : Byte);
  255. begin
  256.     if Amount = 0 then
  257.     return;
  258.     if ToReg >= a0 then begin
  259.     case Amount of
  260.       1..8 :
  261.         begin
  262.         Out_Operation2(op_ADDQ,2,ea_Constant,a7,ea_Register,ToReg);
  263.         Out_Extension(Amount);
  264.         end;
  265.  
  266.       -8..-1 :
  267.         begin
  268.         Out_Operation2(op_SUBQ,2,ea_Constant,a7,ea_Register,ToReg);
  269.         Out_Extension(-Amount);
  270.         end;
  271.       -32768..32767 :
  272.         begin
  273.         Out_Operation2(op_LEA,3,ea_Index,ToReg,ea_Register,ToReg);
  274.         Out_Extension(Amount);
  275.         end;
  276.     else begin
  277.          if Amount > 0 then begin
  278.              Out_Operation2(op_ADDA,4,ea_Constant,a7,ea_Register,ToReg);
  279.              Out_Extension(Amount);
  280.          end else begin
  281.              Out_Operation2(op_SUBA,4,ea_Constant,a7,ea_Register,ToReg);
  282.              Out_Extension(-Amount);
  283.          end;
  284.          end;
  285.     end;
  286.     end else begin
  287.     if Amount > 0 then begin
  288.         Out_Operation2(op_ADD,Size,ea_Constant,a7,ea_Register,ToReg);
  289.         Out_Extension(Amount);
  290.     end else begin
  291.         Out_Operation2(op_SUB,Size,ea_Constant,a7,ea_Register,ToReg);
  292.         Out_Extension(-Amount);
  293.     end;
  294.     end;
  295. end;
  296.  
  297. {
  298.     If the expression Expr is a variable that can be referenced as one
  299.     of the arguments of an assembly command, return true.  Return false
  300.     if the expression requires calculations.
  301.  
  302.     Global variables, typed constants, local variables, and value
  303.     parameters return true if they are simple types (i.e. can be held
  304.     in a register).  Reference parameters, sub-expressions, arrays, etc.
  305.     all return false.  Field references return true if the record reference
  306.     is a simple reference.
  307. }
  308.  
  309. Function SimpleReference(Expr : ExprPtr) : Boolean;
  310. var
  311.     ID : IDPtr;
  312. begin
  313.     if not SimpleType(Expr^.EType) then
  314.     SimpleReference := False;    { Requires a memory reference }
  315.  
  316.     if Expr^.Kind = Var1 then begin
  317.     ID := IDPtr(Expr^.Value);
  318.     case ID^.Object of
  319.       global,
  320.       typed_const : SimpleReference := True;
  321.       local,
  322.       valarg : SimpleReference := (ID^.Level = CurrentBlock^.Level) or
  323.                     (ID^.Level <= 1);
  324.     else
  325.         SimpleReference := False;
  326.     end;
  327.     end;
  328.  
  329.     if Expr^.Kind = period1 then
  330.         if Expr^.Left^.Kind = var1 then
  331.             SimpleReference := SimpleReference(Expr^.Left);
  332.  
  333.     SimpleReference := False;
  334. end;
  335.  
  336.  
  337. {
  338.     Given that the expression satifies "SimpleReference" above,
  339.     write the actual value reference.
  340. }
  341.  
  342. Procedure GetSimpleReference(var EA : EAModes; var Reg : Regs;
  343.                 var Ext1, Ext2 : Integer; Expr : ExprPtr);
  344. var
  345.     ID : IDPtr;
  346.     WasField : Boolean;
  347. begin
  348.     if Expr^.Kind = period1 then begin
  349.     WasField := True;
  350.     Ext2 := Expr^.Value;
  351.     Expr := Expr^.Left;
  352.     end else begin
  353.     WasField := False;
  354.     Ext2 := 0;
  355.     end;
  356.  
  357.     Reg := a7;
  358.     ID := IDPtr(Expr^.Value);
  359.     case ID^.Object of
  360.       typed_const,
  361.       global  : begin
  362.             if WasField then
  363.             EA := ea_Offset
  364.             else
  365.                 EA := ea_Global;
  366.             Ext1 := Integer(ID);
  367.         end;
  368.       valarg,
  369.       local   : begin
  370.             EA := ea_Index;
  371.             Ext1 := ID^.Offset + Ext2;
  372.             Reg := a5;
  373.         end;
  374.     end;
  375. end;
  376.  
  377. Procedure WriteSimpleSource(Expr : ExprPtr; op : OpCodes; Size : Byte;
  378.                 DestEA : EAModes; DestReg : Regs);
  379. var
  380.     SrcEA  : EAModes;
  381.     SrcReg : Regs;
  382.     Ext1,
  383.     Ext2   : Integer;
  384. begin
  385.     GetSimpleReference(SrcEA, SrcReg, Ext1, Ext2, Expr);
  386.     Out_Operation2(op, Size, SrcEA, SrcReg, DestEA, DestReg);
  387.     Out_Extension(Ext1);
  388.     if SrcEA = ea_Offset then
  389.     Out_Extension(Ext2);
  390. end;
  391.  
  392. Procedure WriteSimpleDest(Expr : ExprPtr; op : OpCodes; Size : Byte;
  393.                 SrcEA : EAModes; SrcReg : Regs;
  394.                 SExt1, SExt2 : Integer);
  395. var
  396.     DestEA  : EAModes;
  397.     DestReg : Regs;
  398.     Ext1,
  399.     Ext2    : Integer;
  400. begin
  401.     GetSimpleReference(DestEA, DestReg, Ext1, Ext2, Expr);
  402.     Out_Operation2(op, Size, SrcEA, SrcReg, DestEA, DestReg);
  403.     if Extensions[SrcEA] >= 1 then begin
  404.     Out_Extension(SExt1);
  405.     if Extensions[SrcEA] >= 2 then
  406.         Out_Extension(SExt2);
  407.     end;
  408.     Out_Extension(Ext1);
  409.     if DestEA = ea_Offset then
  410.     Out_Extension(Ext2);
  411. end;
  412.  
  413. Procedure WriteSimpleSingle(Expr : ExprPtr; op : OpCodes; Size : Byte);
  414. var
  415.     EA : EAModes;
  416.     Reg : Regs;
  417.     Ext1,
  418.     Ext2 : Integer;
  419. begin
  420.     GetSimpleReference(EA, Reg, Ext1, Ext2, Expr);
  421.     Out_Operation1(op, Size, EA, Reg);
  422.     Out_Extension(Ext1);
  423.     if EA = ea_Offset then
  424.     Out_Extension(Ext2);
  425. end;
  426.  
  427.  
  428. Procedure Evaluate(Expr : ExprPtr; ToReg : Regs);
  429.     forward;
  430.  
  431. Procedure EvalAddress(Expr : ExprPtr; ToReg : Regs);
  432.     forward;
  433.  
  434.  
  435.  
  436. Procedure ConstantShiftLeft(Shifts : Byte; ToReg : Regs; Size : Byte);
  437. begin
  438.     Shifts := Shifts and 31;
  439.     while Shifts > 0 do begin
  440.     case Shifts of
  441.       1 :    begin
  442.             Out_Operation2(op_ADD,Size,ea_Register,ToReg,
  443.                         ea_Register,ToReg);
  444.             Shifts := 0;
  445.         end;
  446.       2..7 :
  447.         begin
  448.             Out_Operation2(op_LSL,Size,ea_Constant,a7,ea_Register,ToReg);
  449.             Out_Extension(Shifts);
  450.             Shifts := 0;
  451.         end;
  452.       8..15 :
  453.         if Size = 1 then
  454.             Shifts := 0
  455.         else begin
  456.             Out_Operation2(op_LSL,Size,ea_Constant,a7,ea_Register,ToReg);
  457.             Out_Extension(8);
  458.             Shifts := Shifts - 8;
  459.         end;
  460.       16..31 :
  461.         if Size <> 4 then
  462.             Shifts := 0
  463.         else begin
  464.             Out_Operation1(op_SWAP,3,ea_Register,ToReg);
  465.             Out_Operation1(op_CLR,2,ea_Register,ToReg);
  466.             Shifts := Shifts - 16;
  467.         end;
  468.     end;
  469.     end;
  470. end;
  471.  
  472.  
  473. Procedure ConstantShiftRight(Op : OpCodes; Shifts : Byte;
  474.                              ToReg : Regs; Size : Byte);
  475. begin
  476.     Shifts := Shifts and 31;
  477.     while Shifts > 0 do begin
  478.     case Shifts of
  479.       1..7 :
  480.         begin
  481.             Out_Operation2(Op,Size,ea_Constant,a7,
  482.                         ea_Register,ToReg);
  483.             Out_Extension(Shifts);
  484.             Shifts := 0;
  485.         end;
  486.       8..15 :
  487.         if Size = 1 then
  488.             Shifts := 0
  489.         else begin
  490.             Out_Operation2(Op,Size,ea_Constant,a7,
  491.                         ea_Register,ToReg);
  492.             Out_Extension(8);
  493.             Shifts := Shifts - 8;
  494.         end;
  495.       16..31 :
  496.         if Size <> 4 then
  497.             Shifts := 0
  498.         else if Op = op_LSR then begin
  499.             Out_Operation1(op_CLR,2,ea_Register,ToReg);
  500.             Out_Operation1(op_SWAP,3,ea_Register,ToReg);
  501.             Shifts := Shifts - 16;
  502.         end else begin
  503.             Out_Operation1(op_SWAP,3,ea_Register,ToReg);
  504.             Out_Operation1(op_EXT,4,ea_Register,ToReg);
  505.             Shifts := Shifts - 16;
  506.         end;
  507.     end;
  508.     end;
  509. end;
  510.  
  511.  
  512. {
  513.     Push each expression in the list onto the stack, then return
  514.     the total size (in bytes) of the stack load.  This routine
  515.     assumes that all the scratch registers are free.
  516. }
  517.  
  518.  
  519. Function PushArguments(Expr : ExprPtr; ToReg : Regs) : Integer;
  520. var
  521.     Argument : ExprPtr;
  522.     Formal   : IDPtr;
  523.     Total    : Integer;
  524.     Stag     : Byte;
  525.     lab,
  526.     VarSize  : Integer;
  527. begin
  528.     Argument := Expr^.Left;
  529.     Formal   := IDPtr(Expr^.Value);
  530.     Formal   := Formal^.Param;
  531.     Total    := 0;
  532.     while (Argument <> Nil) and (Formal <> Nil) do begin
  533.     VarSize := Formal^.VType^.Size;
  534.     if Formal^.Object = valarg then begin
  535.         STag := VarSize;
  536.         if STag = 1 then
  537.         STag := 2;
  538.         Total := Total + VarSize;
  539.         if SimpleType(Formal^.VType) then begin
  540.         if Argument^.Kind = Const1 then begin
  541.             if STag = 4 then begin
  542.             Out_Operation1(op_PEA,3,ea_Absolute,a7);
  543.             Out_Extension(Argument^.Value);
  544.             end else begin
  545.             Out_Operation1(op_PUSH,2,ea_Constant,a7);
  546.             Out_Extension(Argument^.Value);
  547.             end;
  548.         end else if SimpleReference(Argument) and
  549.                 (Argument^.EType^.Size = STag) then begin
  550.             WriteSimpleSingle(Argument,op_PUSH,STag);
  551.         end else begin
  552.             Evaluate(Argument,ToReg);
  553.             Out_Operation1(op_PUSH,STag,ea_Register,ToReg);
  554.             UnmarkRegister(ToReg);
  555.         end;
  556.         StackLoad := StackLoad + VarSize;
  557.         if Odd(Total) then begin
  558.             Inc(StackLoad);
  559.             Inc(Total);
  560.         end;
  561.         end else begin
  562.         Evaluate(Argument,a0);
  563.         VarSize := Formal^.VType^.Size;
  564.  
  565.         Out_Operation2(op_MOVE,4,ea_Register,a7,ea_Register,a1);
  566.         AddConstant(-VarSize, a1, 4);
  567.         Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Register,d1);
  568.         Out_Extension(Pred(VarSize));
  569.  
  570.         lab := GetLabel();
  571.         Out_Operation1(op_LABEL,3,ea_Label,a7);
  572.         Out_Extension(lab);
  573.         Out_Operation2(op_MOVE,1,ea_PostInc,a0,ea_PostInc,a1);
  574.         Out_Operation2(op_DBRA,3,ea_Register,d1,ea_Label,a7);
  575.         Out_Extension(lab);
  576.  
  577.         AddConstant(-VarSize, a7, 4);
  578.         StackLoad := StackLoad + VarSize;
  579.         UnmarkRegister(a0);
  580.         end;
  581.     end else begin { reference parameter }
  582.         EvalAddress(Argument, a0);
  583.         Out_Operation1(op_PUSH,4,ea_Register,a0);
  584.         StackLoad := StackLoad + 4;
  585.         Total := Total + 4;
  586.         UnmarkRegister(a0);
  587.     end;
  588.     Argument := Argument^.Next;
  589.     Formal := Formal^.Next;
  590.     end;
  591.     PushArguments := Total;
  592. end;
  593.  
  594.  
  595. Function PushFrame(Callee : Integer) : Integer;
  596. var
  597.     Caller : Integer;
  598. begin
  599.     if Callee <= 1 then { global-level routines, which include externs }
  600.     PushFrame := 0
  601.     else begin
  602.     Caller := Pred(CurrentBlock^.Level);
  603.     if Callee = Caller + 1 then { calling child procedure }
  604.         Out_Operation1(op_PUSH,4,ea_Register,a5)
  605.     else if Callee = Caller then begin { same level }
  606.         Out_Operation1(op_PUSH,4,ea_Index,a5);
  607.         Out_Extension(8);
  608.     end else begin
  609.         Out_Operation2(op_MOVE,4,ea_Index,a5,ea_Register,a4);
  610.         Out_Extension(8);
  611.         Caller := Pred(Caller);
  612.         while Caller > Callee do begin
  613.         Out_Operation2(op_MOVE,4,ea_Index,a4,ea_Register,a4);
  614.         Out_Extension(8);
  615.         Caller := Pred(Caller);
  616.         end;
  617.         Out_Operation1(op_PUSH,4,ea_Index,a4);
  618.         Out_Extension(8);
  619.     end;
  620.     StackLoad := StackLoad + 4;
  621.     PushFrame := 4;
  622.     end;
  623. end;
  624.  
  625. {  Load the address of Expr into ToReg.  The Expr must be a valid
  626.    variable reference, not a general expression. }
  627.  
  628. Procedure EvalAddress(Expr : ExprPtr; ToReg : Regs);
  629. var
  630.     Stacked  : Boolean;
  631.     OtherReg : Regs;
  632.     ID       : IDPtr;
  633.     Reg      : Regs;
  634.     WithInfo : WithRecPtr;
  635.     SavedRegs: Integer;
  636. begin
  637.     case Expr^.Kind of
  638.       var1 : begin
  639.         ID := IDPtr(Expr^.Value);
  640.         case ID^.Object of
  641.           global,
  642.           typed_const,
  643.           func,
  644.           proc  :
  645.             begin
  646.                 Out_Operation2(op_MOVE,4,ea_Address,a7,ea_Register,ToReg);
  647.                 Out_Extension(Integer(ID));
  648.             end;
  649.           local,
  650.           valarg :
  651.             begin
  652.                 Reg := GetFramePointer(ID^.Level);
  653.                 if ToReg >= a0 then begin
  654.                 Out_Operation2(op_LEA,3,ea_Index,Reg,ea_Register,ToReg);
  655.                 Out_Extension(ID^.Offset);
  656.                 end else begin
  657.                 Out_Operation2(op_LEA,3,ea_Index,Reg,ea_Register,a4);
  658.                 Out_Extension(ID^.Offset);
  659.                 Out_Operation2(op_MOVE,4,ea_Register,a4,ea_Register,ToReg);
  660.                 end;
  661.             end;
  662.           refarg :
  663.             begin
  664.                 Reg := GetFramePointer(ID^.Level);
  665.                 Out_Operation2(op_MOVE,4,ea_Index,Reg,ea_Register,ToReg);
  666.                 Out_Extension(ID^.Offset);
  667.             end;
  668.         end;
  669.          end;
  670.       field1  : begin
  671.             ID := IDPtr(Expr^.Value);
  672.             WithInfo := WithRecPtr(Expr^.Left);
  673.             Out_Operation2(op_MOVE,4,ea_Index,a7,ea_Register,ToReg);
  674.             Out_Extension(Stackload - WithInfo^.Offset);
  675.             if ID^.Offset <> 0 then
  676.             AddConstant(ID^.Offset, ToReg, 4);
  677.         end;
  678.       period1 : begin
  679.             EvalAddress(Expr^.Left,ToReg);
  680.             AddConstant(Expr^.Value, ToReg, 4);
  681.                 end;
  682.       carat1 : if Expr^.Left^.EType^.Object = ob_file then begin
  683.            SavedRegs := UsedRegs;
  684.            SaveScratchRegisters;
  685.            Evaluate(Expr^.Left,a0);
  686.            Out_Operation1(op_JSR,3,ea_String,a7);
  687.            Out_Extension(Integer("_p%FilePtr"));
  688.            if IOCheck then begin
  689.             Out_Operation1(op_JSR,3,ea_String,a7);
  690.             Out_Extension(Integer("_p%CheckIO"));
  691.            end;
  692.            if ToReg <> a0 then
  693.             Out_Operation2(op_MOVE,4,ea_Register,a0,ea_Register,ToReg);
  694.            UsedRegs := SavedRegs;
  695.            RestoreScratchRegisters;
  696.         end else
  697.            Evaluate(Expr^.Left,ToReg);
  698.       leftbrack1 : 
  699.         with Expr^ do begin
  700.             if Left^.EType = StringType then
  701.             Evaluate(Left, ToReg)
  702.             else
  703.             EvalAddress(Left,ToReg);
  704.             if SimpleReference(Right) and (not RangeCheck) then begin
  705.             WriteSimpleSource(Right,op_ADD,4,ea_Register,ToReg);
  706.             { If it's a simple reference it must be an Integer}
  707.             end else begin
  708.             AllocateDataRegister(OtherReg, Stacked);
  709.             Evaluate(Right, OtherReg);
  710.             if RangeCheck and (Left^.EType <> StringType) then begin
  711.                 Out_Operation1(op_PEA,3,ea_Absolute,a7);
  712.                 Out_Extension((Left^.EType^.Upper -
  713.                        Left^.EType^.Lower) *
  714.                        Left^.EType^.SubType^.Size);
  715.                 Out_Operation1(op_PUSH,4,ea_Register,OtherReg);
  716.                 Out_Operation1(op_JSR,3,ea_String,a7);
  717.                 Out_Extension(Integer("_p%CheckRange"));
  718.             end;
  719.             Out_Operation2(op_ADD,4,ea_Register,OtherReg,
  720.                         ea_Register,ToReg);
  721.             DeallocateDataRegister(OtherReg,Stacked);
  722.             end;
  723.         end;
  724.       type1 : EvalAddress(Expr^.Left, ToReg);
  725.     else
  726.         Writeln('Error in EvalAddress : ', Ord(Expr^.Kind));
  727.     end;
  728.     MarkRegister(ToReg);
  729. end;
  730.  
  731.  
  732. Procedure Evaluate(Expr : ExprPtr; ToReg : Regs);
  733. var
  734.     op : Symbols;
  735.     TagModel : String;
  736.  
  737.     Procedure ConstantOperation(op : OpCodes; STag : Byte;
  738.                     Value : Integer; ToReg : Regs);
  739.     var
  740.     OtherReg : Regs;
  741.     begin
  742.     OtherReg := TemporaryData;
  743.     if (OtherReg < a0) and (Value <= 127) and (Value >= -128) and
  744.        (STag >= 3) and (Value <> 0) then begin
  745.         Out_Operation2(op_MOVEQ,3,ea_Constant,a7,ea_Register,OtherReg);
  746.         Out_Extension(Value);
  747.         Out_Operation2(op,STag,ea_Register,OtherReg,ea_Register,ToReg);
  748.     end else begin
  749.         Out_Operation2(op, STag, ea_Constant,a7,ea_Register,ToReg);
  750.         Out_Extension(Value);
  751.     end;
  752.     end;
  753.  
  754.  
  755.     Procedure Eval_BinaryFloat(offset : Integer);
  756.     var
  757.     SaveUsed : Integer;
  758.     begin
  759.     SaveUsed := UsedRegs;
  760.     SaveScratchRegisters;
  761.     Evaluate(Expr^.Left, d1);
  762.     Evaluate(Expr^.Right, d0);
  763.     if not MathLoaded then begin
  764.         Out_Operation2(op_MOVE,4,ea_String,a7,ea_Register,a6);
  765.         Out_Extension(Integer("_p%MathBase"));
  766.         MathLoaded := True;
  767.     end;
  768.     Out_Operation1(op_JSR,3,ea_Index,a6);
  769.     Out_Extension(Offset);
  770.     if ToReg <> d0 then
  771.         Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  772.     UsedRegs := SaveUsed;
  773.     RestoreScratchRegisters;
  774.     end;
  775.  
  776.  
  777.     Procedure Eval_UnaryFloat(offset : Integer);
  778.     var
  779.     SaveUsed : Integer;
  780.     begin
  781.     SaveUsed := UsedRegs;
  782.     SaveScratchRegisters;
  783.     Evaluate(Expr^.Left, d0);
  784.     if not MathLoaded then begin
  785.         Out_Operation2(op_MOVE,4,ea_String,a7,ea_Register,a6);
  786.         Out_Extension(Integer("_p%MathBase"));
  787.         MathLoaded := True;
  788.     end;
  789.     Out_Operation1(op_JSR,3,ea_Index,a6);
  790.     Out_Extension(Offset);
  791.     if ToReg <> d0 then
  792.         Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  793.     UsedRegs := SaveUsed;
  794.     RestoreScratchRegisters;
  795.     end;
  796.  
  797.  
  798.     Procedure Eval_32BitMath(math : String);
  799.     var
  800.     SavedRegs : Integer;
  801.  
  802.     Procedure EvalToStack(Expr : ExprPtr);
  803.      begin
  804.         if Expr^.Kind = Const1 then begin
  805.         Out_Operation1(op_PEA,3,ea_Absolute,a7);
  806.         Out_Extension(Expr^.Value);
  807.         end else if SimpleReference(Expr) then begin
  808.         WriteSimpleSingle(Expr,op_PUSH,4);
  809.         end else begin
  810.         Evaluate(Expr, ToReg);
  811.         Out_Operation1(op_PUSH,4,ea_Register,ToReg);
  812.         end;
  813.         StackLoad := StackLoad + 4;
  814.         UnmarkRegister(ToReg);
  815.     end;
  816.  
  817.     begin
  818.     with Expr^ do begin
  819.         SavedRegs := UsedRegs;
  820.         SaveScratchRegisters;
  821.         EvalToStack(Left);
  822.         EvalToStack(Right);
  823.         Out_Operation1(op_JSR,3,ea_String,a7);
  824.         Out_Extension(Integer(Math));
  825.         if ToReg <> d0 then
  826.         Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  827.         PopStackSpace(8);
  828.         UsedRegs := SavedRegs;
  829.         RestoreScratchRegisters;
  830.     end;
  831.     end;
  832.  
  833.  
  834.     Procedure Eval_BinaryMath(op : OpCodes; UseSize : Boolean);
  835.     { add, sub, or, and, xor }
  836.     var
  837.     OtherReg : Regs;
  838.     Stacked  : Boolean;
  839.     STag     : Byte;
  840.     begin
  841.     with Expr^ do begin
  842.         if UseSize then
  843.         STag := EType^.Size
  844.         else
  845.         STag := 3;
  846.  
  847.         if Left^.Kind = Const1 then begin
  848.         Evaluate(Right, ToReg);
  849.         ConstantOperation(op, STag, Left^.Value, ToReg);
  850.         end else if SimpleReference(Left) then begin
  851.         Evaluate(Right, ToReg);
  852.         WriteSimpleSource(Left,op,STag,ea_Register,ToReg);
  853.         end else begin
  854.         AllocateDataRegister(OtherReg, Stacked);
  855.         Evaluate(Left, OtherReg);
  856.         Evaluate(Right, ToReg);
  857.         Out_Operation2(op,STag,ea_Register,OtherReg,ea_Register,ToReg);
  858.         DeallocateDataRegister(OtherReg, Stacked);
  859.         end;
  860.     end;
  861.     end;
  862.  
  863.  
  864.     Procedure Eval_UnaryMath(op : OpCodes);
  865.     begin
  866.     with Expr^ do begin
  867.         Evaluate(Left, ToReg);
  868.         Out_Operation1(op,EType^.Size,ea_Register,ToReg);
  869.     end;
  870.     end;
  871.  
  872.  
  873.     Procedure Eval_Boolean;
  874.     { Boolean and & or, possibly with short circuits }
  875.     var
  876.     OtherReg : Regs;
  877.     Stacked  : Boolean;
  878.     ShortLab : Integer;
  879.     op       : OpCodes;
  880.     Temp     : ExprPtr;
  881.     begin
  882.     with Expr^ do begin
  883.  
  884.         ShortLab := GetLabel;
  885.  
  886.         if Left^.Kind = Const1 then begin
  887.         Temp := Left;
  888.         Left := Right;
  889.         Right := Temp;
  890.         end;
  891.  
  892.         Evaluate(Left, ToReg);
  893.  
  894.         { If the right half is a constant, it must just be an }
  895.         { 'enabler' - FALSE for OR expressions, or TRUE for   }
  896.         { AND expressions.  Otherwise the expression would    }
  897.         { have optimized out. }
  898.  
  899.         if Right^.Kind = Const1 then
  900.         return;
  901.  
  902.         Out_Operation1(op_TST,1,ea_Register,ToReg);
  903.  
  904.         if Kind = or1 then
  905.         Out_Operation1(op_BNE,3,ea_Label,a7)
  906.         else
  907.         Out_Operation1(op_BEQ,3,ea_Label,a7);
  908.         Out_Extension(ShortLab);
  909.  
  910.         case Kind of
  911.           or1  : op := op_OR;
  912.           and1 : op := op_AND;
  913.         end;
  914.  
  915.         { We know at this point that the left half of the equation }
  916.         { is an enabler - otherwise the branch would have taken    }
  917.         { effect.  Therefore the value of the right half of the    }
  918.         { equation will determine the overall value                }
  919.  
  920.         UnmarkRegister(ToReg);
  921.  
  922.         Evaluate(Right, ToReg);
  923.  
  924.         Out_Operation1(op_LABEL,3,ea_Label,a7);
  925.         Out_Extension(ShortLab);
  926.     end;
  927.     end;
  928.  
  929.  
  930.     Procedure Eval_Comparison;
  931.     var
  932.     STag     : Byte;
  933.     OtherReg : Regs;
  934.     Stacked  : Boolean;
  935.  
  936.     Function LeftToRight : OpCodes;
  937.     begin
  938.         case Expr^.Kind of
  939.           greater1  : LeftToRight := op_SLT;
  940.           less1    : LeftToRight := op_SGT;
  941.           notgreater1 : LeftToRight := op_SGE;
  942.           notless1    : LeftToRight := op_SLE;
  943.           equal1    : LeftToRight := op_SEQ;
  944.           notequal1    : LeftToRight := op_SNE;
  945.         end;
  946.     end;
  947.  
  948.  
  949.     Function RightToLeft : OpCodes;
  950.     begin
  951.         case Expr^.Kind of
  952.           greater1  : RightToLeft := op_SGT;
  953.           less1    : RightToLeft := op_SLT;
  954.           notgreater1 : RightToLeft := op_SLE;
  955.           notless1    : RightToLeft := op_SGE;
  956.           equal1    : RightToLeft := op_SEQ;
  957.           notequal1    : RightToLeft := op_SNE;
  958.         end;
  959.     end;
  960.  
  961.  
  962.     begin
  963.     with Expr^ do begin
  964.         if Left^.EType = RealType then begin
  965.         Eval_BinaryFloat(-42);
  966.         Out_Operation1(LeftToRight, 3, ea_Register, ToReg);
  967.         end else begin
  968.         STag := Left^.EType^.Size;
  969.  
  970.         if Right^.Kind = Const1 then begin
  971.             Evaluate(Left, ToReg);
  972.             ConstantOperation(op_CMP,STag,Right^.Value,ToReg);
  973.             Out_Operation1(RightToLeft,3,ea_Register,ToReg);
  974.         end else if Left^.Kind = Const1 then begin
  975.             Evaluate(Right, ToReg);
  976.             ConstantOperation(op_CMP,STag, Left^.Value, ToReg);
  977.             Out_Operation1(LeftToRight,3,ea_Register,ToReg);
  978.         end else if SimpleReference(Right) then begin
  979.             Evaluate(Left, ToReg);
  980.             WriteSimpleSource(Right,op_CMP,STag,ea_Register,ToReg);
  981.             Out_Operation1(RightToLeft,3,ea_Register,ToReg);
  982.         end else if SimpleReference(Left) then begin
  983.             Evaluate(Right, ToReg);
  984.             WriteSimpleSource(Left,op_CMP,STag,ea_Register,ToReg);
  985.             Out_Operation1(LeftToRight,3,ea_Register,ToReg);
  986.         end else begin
  987.             AllocateDataRegister(OtherReg, Stacked);
  988.             Evaluate(Right, OtherReg);
  989.             Evaluate(Left, ToReg);
  990.             Out_Operation2(op_CMP,STag,ea_Register,OtherReg,
  991.                         ea_Register,ToReg);
  992.             Out_Operation1(RightToLeft,3,ea_Register,ToReg);
  993.             DeallocateDataRegister(OtherReg, Stacked);
  994.         end;
  995.         end;
  996.     end;
  997.     end;
  998.  
  999.     Procedure LoadIDValue(ID : IDPtr);
  1000.     var
  1001.     STag : Byte;
  1002.     Simp : Boolean;
  1003.     OtherReg : Regs;
  1004.     begin
  1005.     STag := ID^.VType^.Size;
  1006.     Simp := SimpleType(ID^.VType);
  1007.     case ID^.Object of
  1008.       typed_const,
  1009.       global :
  1010.         if Simp then begin
  1011.             Out_Operation2(op_MOVE,STag,ea_Global,a7,ea_Register,ToReg);
  1012.             Out_Extension(Integer(ID));
  1013.         end else begin
  1014.             Out_Operation2(op_MOVE,4,ea_Address,a7,ea_Register,ToReg);
  1015.             Out_Extension(Integer(ID));
  1016.         end;
  1017.       local,
  1018.       valarg :
  1019.         begin
  1020.             OtherReg := GetFramePointer(ID^.Level);
  1021.             if Simp then begin
  1022.             Out_Operation2(op_MOVE,STag,ea_Index,OtherReg,
  1023.                             ea_Register,ToReg);
  1024.             Out_Extension(ID^.Offset);
  1025.             end else begin
  1026.             if ToReg >= a0 then begin
  1027.                 Out_Operation2(op_LEA,3,ea_Index,OtherReg,
  1028.                             ea_Register,ToReg);
  1029.                 Out_Extension(ID^.Offset);
  1030.             end else begin
  1031.                 Out_Operation2(op_LEA,3,ea_Index,OtherReg,
  1032.                             ea_Register,a4);
  1033.                 Out_Extension(ID^.Offset);
  1034.                 Out_Operation2(op_MOVE,4,ea_Register,a4,
  1035.                             ea_Register,ToReg);
  1036.             end;
  1037.             end;
  1038.          end;
  1039.       refarg :
  1040.         begin
  1041.             OtherReg := GetFramePointer(ID^.Level);
  1042.             if Simp then begin
  1043.             Out_Operation2(op_MOVE,4,ea_Index,OtherReg,
  1044.                         ea_Register,a4);
  1045.             Out_Extension(ID^.Offset);
  1046.             Out_Operation2(op_MOVE,STag,ea_Indirect,a4,
  1047.                             ea_Register,ToReg);
  1048.             end else begin
  1049.             Out_Operation2(op_MOVE,4,ea_Index,OtherReg,
  1050.                         ea_Register,ToReg);
  1051.             Out_Extension(ID^.Offset);
  1052.             end;
  1053.         end;
  1054.     end;
  1055.     end;
  1056.  
  1057.  
  1058.     Procedure Eval_Shift;
  1059.     var
  1060.     OtherReg : Regs;
  1061.     Stacked    : Boolean;
  1062.     begin
  1063.     with Expr^ do begin
  1064.         if Right^.Kind = Const1 then begin
  1065.         Evaluate(Left, ToReg);
  1066.         if Kind = shl1 then
  1067.             ConstantShiftLeft(Right^.Value, ToReg, EType^.Size)
  1068.         else
  1069.             ConstantShiftRight(op_LSR,Right^.Value,ToReg,EType^.Size);
  1070.         end else begin
  1071.         AllocateDataRegister(OtherReg, Stacked);
  1072.         Evaluate(Left, ToReg);
  1073.         Evaluate(Right, OtherReg);
  1074.         if Kind = shl1 then
  1075.             Out_Operation2(op_LSL,EType^.Size,ea_Register,OtherReg,
  1076.                             ea_Register,ToReg)
  1077.         else
  1078.             Out_Operation2(op_LSR,EType^.Size,ea_Register,OtherReg,
  1079.                             ea_Register,ToReg);
  1080.         DeallocateDataRegister(OtherReg, Stacked);
  1081.         end;
  1082.     end;
  1083.     end;
  1084.  
  1085.  
  1086.     Procedure Eval_Constant;
  1087.     begin
  1088.     with Expr^ do begin
  1089.         Out_Operation2(op_MOVE,EType^.Size,ea_Constant,a7,
  1090.                         ea_Register,ToReg);
  1091.         Out_Extension(Value);
  1092.     end;
  1093.     end;
  1094.                 
  1095.  
  1096.  
  1097.     { Generate the value of an array reference.  Cases where the index
  1098.       is a constant will not occur - they are converted to period1 nodes
  1099.       in Expr.p and Optimize.p }
  1100.  
  1101.     Procedure Eval_ArrayReference;
  1102.     var
  1103.     AReg,
  1104.     DReg : Regs;
  1105.     Stacked : Boolean;
  1106.     begin
  1107.     with Expr^ do begin
  1108.         if ToReg >= a0 then
  1109.         AReg := ToReg
  1110.         else
  1111.         AllocateAddressRegister(AReg, Stacked);
  1112.         if Left^.EType = StringType then
  1113.         Evaluate(Left, AReg)
  1114.         else
  1115.         EvalAddress(Left, AReg);
  1116.         if SimpleReference(Right) and (not RangeCheck) then begin
  1117.         WriteSimpleSource(Right,op_ADDA,4,ea_Register,AReg);
  1118.         if SimpleType(EType) then
  1119.             Out_Operation2(op_MOVE,EType^.Size,ea_Indirect,AReg,
  1120.                             ea_Register,ToReg)
  1121.         else if AReg <> ToReg then
  1122.             Out_Operation2(op_MOVE,4,ea_Register,AReg,
  1123.                         ea_Register,ToReg);
  1124.         if AReg <> ToReg then
  1125.             DeallocateAddressRegister(AReg, Stacked);
  1126.         end else begin
  1127.         if ToReg < a0 then
  1128.             DReg := ToReg
  1129.         else
  1130.             AllocateDataRegister(DReg, Stacked); { will not happen with above }
  1131.         Evaluate(Right, DReg);
  1132.         if RangeCheck and (Left^.EType <> StringType) then begin
  1133.             Out_Operation1(op_PEA,3,ea_Absolute,a7);
  1134.             Out_Extension((Left^.EType^.Upper -
  1135.                    Left^.EType^.Lower) *
  1136.                    Left^.EType^.SubType^.Size);
  1137.             Out_Operation1(op_PUSH,4,ea_Register,DReg);
  1138.             Out_Operation1(op_JSR,3,ea_String,a7);
  1139.             Out_Extension(Integer("_p%CheckRange"));
  1140.         end;
  1141.         if SimpleType(EType) then begin
  1142.             Out_Operation2(op_MOVE,EType^.Size,ea_RegInd,AReg,
  1143.                             ea_Register,DReg);
  1144.             Out_Extension(Ord(DReg));
  1145.         end else begin
  1146.             if DReg = ToReg then
  1147.             Out_Operation2(op_ADD,4,ea_Register,AReg,
  1148.                             ea_Register,DReg)
  1149.             else
  1150.             Out_Operation2(op_ADDA,4,ea_Register,DReg,
  1151.                             ea_Register,AReg);
  1152.         end;
  1153.         if DReg = ToReg then
  1154.             DeallocateAddressRegister(AReg, Stacked)
  1155.         else
  1156.             DeallocateDataRegister(DReg, Stacked);
  1157.         end;
  1158.     end;
  1159.     end;
  1160.  
  1161.  
  1162.     Procedure Eval_Dereference;
  1163.     var
  1164.     OtherReg : Regs;
  1165.     Stacked  : Boolean;
  1166.     SaveUsed : Integer;
  1167.     begin
  1168.     with Expr^ do begin
  1169.         if Left^.EType^.Object = ob_file then begin
  1170.         SaveUsed := UsedRegs;
  1171.         SaveScratchRegisters;
  1172.         Evaluate(Left,a0);
  1173.         Out_Operation1(op_JSR,3,ea_String,a7);
  1174.         Out_Extension(Integer("_p%FilePtr"));
  1175.         if IOCheck then begin
  1176.             Out_Operation1(op_JSR,3,ea_String,a7);
  1177.             Out_Extension(Integer("_p%CheckIO"));
  1178.         end;
  1179.         Out_Operation2(op_MOVE,EType^.Size,ea_Indirect,a0,
  1180.                             ea_Register,ToReg);
  1181.         UsedRegs := SaveUsed;
  1182.         RestoreScratchRegisters;
  1183.         end else if SimpleType(EType) then begin
  1184.         if ToReg < a0 then
  1185.             AllocateAddressRegister(OtherReg, Stacked)
  1186.         else
  1187.             OtherReg := ToReg;
  1188.         Evaluate(Left, OtherReg);
  1189.         Out_Operation2(op_MOVE,EType^.Size,ea_Indirect,OtherReg,
  1190.                             ea_Register,ToReg);
  1191.         if ToReg < a0 then
  1192.             DeallocateAddressRegister(OtherReg, Stacked);
  1193.         end else
  1194.         Evaluate(Left, ToReg);
  1195.     end;
  1196.     end;
  1197.  
  1198.  
  1199.     Procedure Eval_RecordReference;
  1200.     var
  1201.     OtherReg : Regs;
  1202.     Stacked  : Boolean;
  1203.     begin
  1204.     with Expr^ do begin
  1205.         if SimpleType(EType) then begin
  1206.         if ToReg < a0 then
  1207.             AllocateAddressRegister(OtherReg, Stacked)
  1208.         else
  1209.             OtherReg := ToReg;
  1210.         EvalAddress(Left,OtherReg);
  1211.         Out_Operation2(op_MOVE,EType^.Size,ea_Index,OtherReg,
  1212.                             ea_Register,ToReg);
  1213.         Out_Extension(Value);
  1214.         if ToReg < a0 then
  1215.             DeallocateAddressRegister(OtherReg, Stacked);
  1216.         end else begin
  1217.         EvalAddress(Left,ToReg);
  1218.         AddConstant(Value, ToReg, 4);
  1219.         end;
  1220.     end;
  1221.     end;
  1222.  
  1223.  
  1224.     Procedure DoOpen(AccessMode : Short);
  1225.  
  1226.     {
  1227.     This routine handles both open and reopen, depending on the
  1228.     AccessMode sent to it.  This is just passed on to the DOS routine.
  1229.  
  1230.     OpenExpr:
  1231.         Kind: stanfunc1
  1232.         Value: 7 or 8 (reopen or open)
  1233.         Left Right
  1234.            /         \
  1235.           /           \
  1236.     File Var Expr      file name expr (string)
  1237.     Next
  1238.         \
  1239.          \
  1240.           Buffer Size
  1241.      }
  1242.  
  1243.     var
  1244.     BufferSize    : ExprPtr;
  1245.     SaveUsed    : Integer;
  1246.     begin
  1247.     SaveUsed := UsedRegs;
  1248.     SaveScratchRegisters;
  1249.     with Expr^.Right^ do begin
  1250.         if Kind = Const1 then begin
  1251.         Out_Operation1(op_PUSH,4,ea_Constant,a7);
  1252.         Out_Extension(Value);
  1253.         end else if Kind = Quote1 then begin
  1254.         Out_Operation1(op_PUSH,4,ea_Literal,a7);
  1255.         Out_Extension(Value);
  1256.         end else begin
  1257.         Evaluate(Expr^.Right, d0);
  1258.         Out_Operation1(op_PUSH,4,ea_Register,d0);
  1259.         UnmarkRegister(d0);
  1260.         end;
  1261.     end;
  1262.  
  1263.     StackLoad := StackLoad + 4;    
  1264.     Evaluate(Expr^.Left,a0);
  1265.  
  1266.     Out_Operation2(op_MOVE,2,ea_Constant,a7,ea_Index,a0);
  1267.     Out_Extension(AccessMode);
  1268.     Out_Extension(30);
  1269.  
  1270.     Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Index,a0);
  1271.     Out_Extension(Expr^.Left^.EType^.SubType^.Size);
  1272.     Out_Extension(24);
  1273.  
  1274.     BufferSize := Expr^.Left^.Next;
  1275.     if BufferSize^.Kind = Const1 then begin
  1276.         Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Index,a0);
  1277.         Out_Extension(BufferSize^.Value);
  1278.     end else if SimpleReference(BufferSize) then begin
  1279.         WriteSimpleSource(BufferSize,op_MOVE,4,ea_Index,a0);
  1280.     end else begin
  1281.         Evaluate(BufferSize,d0);
  1282.         Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Index,a0);
  1283.     end;
  1284.     Out_Extension(20);
  1285.  
  1286.     Out_Operation1(op_PUSH,4,ea_Register,a0);
  1287.     Out_Operation1(op_JSR,3,ea_String,a7);
  1288.     Out_Extension(Integer("_p%Open"));
  1289.  
  1290.     if ToReg <> d0 then
  1291.         Out_Operation2(op_MOVE,1,ea_Register,d0,ea_Register,ToReg);
  1292.  
  1293.     AddConstant(8, a7, 4);
  1294.     StackLoad := StackLoad - 4;
  1295.  
  1296.     UsedRegs := SaveUsed;
  1297.     RestoreScratchRegisters;
  1298.     MathLoaded := False;
  1299.     end;
  1300.  
  1301.  
  1302.     Procedure Eval_StandardFunction;
  1303.     var
  1304.     Stacked  : Boolean;
  1305.     Lab      : Integer;
  1306.     STag     : Byte;
  1307.     SaveUsed : Integer;
  1308.     OtherReg : Regs;
  1309.     begin
  1310.     STag := Expr^.Left^.EType^.Size;
  1311.     case Expr^.Value of
  1312.     {Ord} 1,
  1313.     {Chr} 2,  : Evaluate(Expr^.Left,ToReg);
  1314.     {Odd} 3   : begin
  1315.             Evaluate(Expr^.Left,ToReg);
  1316.             ConstantOperation(op_AND,STag,1,ToReg);
  1317.             Out_Operation1(op_SNE,3,ea_Register,ToReg);
  1318.         end;
  1319.     {Abs} 4   : if Expr^.EType = RealType then begin
  1320.             Eval_UnaryFloat(-54);
  1321.         end else begin
  1322.             Lab := GetLabel;
  1323.             Evaluate(Expr^.Left, ToReg);
  1324.             Out_Operation1(op_TST,STag,ea_Register,ToReg);
  1325.             Out_Operation1(op_BPL,3,ea_Label,a7);
  1326.             Out_Extension(Lab);
  1327.             Out_Operation1(op_NEG,STag,ea_Register,ToReg);
  1328.             Out_Operation1(op_LABEL,3,ea_Label,a7);
  1329.             Out_Extension(Lab);
  1330.         end;
  1331.     {Succ} 5  : begin
  1332.             Evaluate(Expr^.Left,ToReg);
  1333.             AddConstant(1, ToReg, STag);
  1334.         end;
  1335.     {Pred} 6  : begin
  1336.             Evaluate(Expr^.Left,ToReg);
  1337.             AddConstant(-1, ToReg, STag);
  1338.         end;
  1339.     {ReOpen} 7 : DoOpen(1005);
  1340.     {Open}   8 : DoOpen(1006);
  1341.     {EOF} 9   : begin
  1342.             AllocateAddressRegister(OtherReg, Stacked);
  1343.             Evaluate(Expr^.Left,OtherReg);
  1344.             Out_Operation2(op_MOVE,1,ea_Index,OtherReg,
  1345.                         ea_Register,ToReg);
  1346.             Out_Extension(29);
  1347.             DeallocateAddressRegister(OtherReg, Stacked);
  1348.         end;
  1349.  {Trunc}  10  : Eval_UnaryFloat(-30);
  1350.  {Round}  11  : begin
  1351.             SaveUsed := UsedRegs;
  1352.             SaveScratchRegisters;
  1353.             Evaluate(Expr^.Left, d0);
  1354.             Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Register,d1);
  1355.             Out_Extension(Integer(0.5));
  1356.             if not MathLoaded then begin
  1357.             Out_Operation2(op_MOVE,4,ea_String,a7,ea_Register,a6);
  1358.             Out_Extension(Integer("_p%MathBase"));
  1359.             MathLoaded := True;
  1360.             end;
  1361.             Out_Operation1(op_JSR,3,ea_Index,a6);
  1362.             Out_Extension(-66);
  1363.             Out_Operation1(op_JSR,3,ea_Index,a6);
  1364.             Out_Extension(-90);
  1365.             Out_Operation1(op_JSR,3,ea_Index,a6);
  1366.             Out_Extension(-30);
  1367.             if ToReg <> d0 then
  1368.             Out_Operation2(op_MOVE,4,ea_Register,d0,
  1369.                             ea_Register,ToReg);
  1370.             UsedRegs := SaveUsed;
  1371.             RestoreScratchRegisters;
  1372.         end;
  1373.  { Float } 12 : Eval_UnaryFloat(-36);
  1374.  { Floor } 13 : Eval_UnaryFloat(-90);
  1375.  { Ceil }  14 : Eval_UnaryFloat(-96);
  1376.  { SizeOf }
  1377.  
  1378.  { Adr }   16 : EvalAddress(Expr^.Left, ToReg);
  1379.  { Bit }
  1380.  { Sqr }   18 : begin
  1381.             SaveUsed := UsedRegs;
  1382.             SaveScratchRegisters;
  1383.             Evaluate(Expr^.Left, d0);
  1384.             Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,d1);
  1385.             if not MathLoaded then begin
  1386.             Out_Operation2(op_MOVE,4,ea_String,a7,ea_Register,a6);
  1387.             Out_Extension(Integer("_p%MathBase"));
  1388.             MathLoaded := True;
  1389.             end;
  1390.             Out_Operation1(op_JSR,3,ea_Index,a6);
  1391.             Out_Extension(-78);
  1392.             if ToReg <> d0 then
  1393.             Out_Operation2(op_MOVE,4,ea_Register,d0,
  1394.                             ea_Register,ToReg);
  1395.             UsedRegs := SaveUsed;
  1396.             RestoreScratchRegisters;
  1397.         end;
  1398.       19..25 : { Sqr, Sin, Cos, Sqrt, Tan, ArcTan, Ln, Exp }
  1399.         with Expr^ do begin
  1400.         SaveUsed := UsedRegs;
  1401.         SaveScratchRegisters;
  1402.         if Left^.Kind = Const1 then begin
  1403.             Out_Operation1(op_PEA,3,ea_Absolute,a7);
  1404.             Out_Extension(Expr^.Value);
  1405.         end else if SimpleReference(Expr) then begin
  1406.             WriteSimpleSingle(Expr,op_PUSH,4);
  1407.         end else begin
  1408.             Evaluate(Expr^.Left, ToReg);
  1409.             Out_Operation1(op_PUSH,4,ea_Register,ToReg);
  1410.         end;
  1411.         Out_Operation1(op_JSR,3,ea_String,a7);
  1412.         case Value of
  1413.           19 : Out_Extension(Integer("_p%sin"));
  1414.           20 : Out_Extension(Integer("_p%cos"));
  1415.           21 : Out_Extension(Integer("_p%sqrt"));
  1416.           22 : Out_Extension(Integer("_p%tan"));
  1417.           23 : Out_Extension(Integer("_p%atn"));
  1418.           24 : Out_Extension(Integer("_p%ln"));
  1419.           25 : Out_Extension(Integer("_p%exp"));
  1420.         end;
  1421.         AddConstant(4, a7, 4);
  1422.         if ToReg <> d0 then
  1423.             Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  1424.                 UsedRegs := SaveUsed;
  1425.                 RestoreScratchRegisters;
  1426.         end;
  1427.     end;
  1428.     end;
  1429.  
  1430.  
  1431.     Procedure Eval_FunctionCall;
  1432.     var
  1433.     SaveUsed : Integer;
  1434.     ID       : IDPtr;
  1435.     PushSize : Integer;
  1436.     begin
  1437.     SaveUsed := UsedRegs;
  1438.     SaveScratchRegisters;
  1439.     PushSize := PushArguments(Expr, ToReg);
  1440.     ID := IDPtr(Expr^.Value);
  1441.     PushSize := PushSize + PushFrame(ID^.Level);
  1442.     Out_Operation1(op_JSR,3,ea_Global,a7);
  1443.     Out_Extension(Integer(ID));
  1444.     PopStackSpace(PushSize);
  1445.     if ToReg <> d0 then
  1446.         Out_Operation2(op_MOVE,4,ea_Register,d0,ea_Register,ToReg);
  1447.     UsedRegs := SaveUsed;
  1448.     RestoreScratchRegisters;
  1449.     MathLoaded := False;
  1450.     end;
  1451.  
  1452.  
  1453.  
  1454.     Procedure Eval_FieldReference;
  1455.     var
  1456.     WithInfo : WithRecPtr;
  1457.     Stacked  : Boolean;
  1458.     STag     : Byte;
  1459.     OtherReg : Regs;
  1460.     ID       : IDPtr;
  1461.     begin
  1462.     ID := IDPtr(Expr^.Value);
  1463.     WithInfo := WithRecPtr(Expr^.Left);
  1464.     if SimpleType(Expr^.EType) then begin
  1465.         STag := ID^.VType^.Size;
  1466.         if ToReg < a0 then
  1467.         AllocateAddressRegister(OtherReg, Stacked)
  1468.         else
  1469.         OtherReg := ToReg;
  1470.         Out_Operation2(op_MOVE,4,ea_Index,a7,ea_Register,OtherReg);
  1471.         Out_Extension(StackLoad - WithInfo^.Offset);
  1472.  
  1473.         Out_Operation2(op_MOVE,STag,ea_Index,OtherReg,ea_Register,ToReg);
  1474.         Out_Extension(ID^.Offset);
  1475.         if ToReg < a0 then
  1476.         DeallocateAddressRegister(OtherReg, Stacked);
  1477.     end else begin
  1478.         Out_Operation2(op_MOVE,4,ea_Index,a7,ea_Register,ToReg);
  1479.         Out_Extension(StackLoad - WithInfo^.Offset);
  1480.         AddConstant(ID^.Offset, ToReg, 4);
  1481.     end;
  1482.     end;
  1483.  
  1484.  
  1485.  
  1486.     { Return the power of 2 represented by Value, or -1 if it's not
  1487.       a power of 2 }
  1488.  
  1489.     Function GetShifts(Value : Integer) : Integer;
  1490.     var
  1491.     Compare : Integer;
  1492.     Shifts  : Integer;
  1493.     begin
  1494.     Shifts := 0;
  1495.     Compare := 1;
  1496.     repeat
  1497.         if Compare = Value then
  1498.         GetShifts := Shifts;
  1499.         Inc(Shifts);
  1500.         Compare := Compare shl 1;
  1501.     until Shifts > 30;
  1502.     GetShifts := -1;
  1503.     end;
  1504.  
  1505.  
  1506.     Procedure Eval_Multiplier;
  1507.     var
  1508.     Shifts   : Integer;
  1509.     begin
  1510.     with Expr^ do begin
  1511.         if Left^.Kind = Const1 then begin
  1512.         Shifts := GetShifts(Left^.Value);
  1513.         if Shifts = 0 then begin
  1514.             Evaluate(PromoteTypeA(Right,IntType), ToReg);
  1515.             Return;
  1516.         end;
  1517.         if Shifts < 0 then begin
  1518.             if Left^.EType^.Size = 4 then
  1519.             Eval_32BitMath("_p%lmul")
  1520.             else
  1521.             Eval_BinaryMath(op_MULS,False);
  1522.         end else begin
  1523.             Evaluate(PromoteTypeA(Right,IntType), ToReg);
  1524.             ConstantShiftLeft(Shifts, ToReg, 4);
  1525.         end;
  1526.         end else begin
  1527.         if Left^.EType^.Size = 4 then
  1528.             Eval_32BitMath("_p%lmul")
  1529.         else
  1530.             Eval_BinaryMath(op_MULS,False);
  1531.         end;
  1532.     end;
  1533.     end;
  1534.  
  1535.  
  1536.     Procedure Eval_Divisor;
  1537.     var
  1538.     Shifts   : Integer;
  1539.     begin
  1540.     with Expr^ do begin
  1541.         if Left^.Kind = Const1 then begin
  1542.         Shifts := GetShifts(Left^.Value);
  1543.         if Shifts = 0 then begin
  1544.             Evaluate(Right, ToReg);
  1545.             Return;
  1546.         end;
  1547.         if Shifts < 0 then begin
  1548.             if Left^.EType^.Size = 4 then
  1549.             Eval_32BitMath("_p%ldiv")
  1550.             else
  1551.             Eval_BinaryMath(op_DIVS,False);
  1552.         end else begin
  1553.             Evaluate(Right, ToReg);
  1554.             ConstantShiftRight(op_ASR,Shifts, ToReg, 4);
  1555.         end;
  1556.         end else begin
  1557.         if Left^.EType^.Size = 4 then
  1558.             Eval_32BitMath("_p%ldiv")
  1559.         else
  1560.             Eval_BinaryMath(op_DIVS,False);
  1561.         end;
  1562.     end;
  1563.     end;
  1564.  
  1565.  
  1566.     Procedure Eval_Modulus;
  1567.     var
  1568.     Shifts   : Integer;
  1569.     begin
  1570.     with Expr^ do begin
  1571.         if Left^.Kind = Const1 then begin
  1572.         Shifts := GetShifts(Left^.Value);
  1573.         if Shifts = 0 then begin
  1574.             Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Register,ToReg);
  1575.             Out_Extension(0);
  1576.             Return;
  1577.         end;
  1578.         if Shifts < 0 then begin
  1579.             if Left^.EType^.Size = 4 then
  1580.             Eval_32BitMath("_p%lrem")
  1581.             else begin
  1582.             Eval_BinaryMath(op_DIVS,False);
  1583.             Out_Operation1(op_SWAP,3,ea_Register,ToReg);
  1584.             end;
  1585.         end else begin
  1586.             Evaluate(Right, ToReg);
  1587.             ConstantOperation(op_AND,Expr^.EType^.Size,
  1588.                     Pred(1 shl shifts), ToReg);
  1589.         end;
  1590.         end else begin
  1591.         if Left^.EType^.Size = 4 then
  1592.             Eval_32BitMath("_p%lrem")
  1593.         else begin
  1594.             Eval_BinaryMath(op_DIVS,False);
  1595.             Out_Operation1(op_SWAP,3,ea_Register,ToReg);
  1596.         end;
  1597.         end;
  1598.     end;
  1599.     end;
  1600.  
  1601.  
  1602. begin
  1603.     if Expr^.EType = BadType then
  1604.     return;
  1605.  
  1606.     op := Expr^.Kind;
  1607.     TagModel := ". \t";
  1608.  
  1609.     if op <= minus1 then begin
  1610.     if op <= xor1 then begin
  1611.         case op of
  1612.           and1    : if (Expr^.EType = BoolType) and ShortCircuit then
  1613.                   Eval_Boolean
  1614.               else
  1615.                   Eval_BinaryMath(op_AND,True);
  1616.           const1    : Eval_Constant;
  1617.           div1    : Eval_Divisor;
  1618.           func1    : Eval_FunctionCall;
  1619.           mod1    : Eval_Modulus;
  1620.           not1    : Eval_UnaryMath(op_NOT);
  1621.           or1    : if (Expr^.EType = BoolType) and ShortCircuit then
  1622.                   Eval_Boolean
  1623.               else
  1624.                   Eval_BinaryMath(op_OR,True);
  1625.           shl1    : Eval_Shift;
  1626.           shr1    : Eval_Shift;
  1627.           type1    : Evaluate(Expr^.Left, ToReg);
  1628.           var1    : LoadIDValue(IDPtr(Expr^.Value));
  1629.           xor1    : Eval_BinaryMath(op_EOR,True);
  1630.         else
  1631.         Writeln(OutFile, 'Did not do: ', Ord(op));
  1632.         end;
  1633.     end else begin
  1634.         case op of
  1635.           asterisk1    : if Expr^.EType = RealType then
  1636.                   Eval_BinaryFloat(-78)
  1637.               else
  1638.                   Eval_Multiplier;
  1639.           equal1    : Eval_Comparison;
  1640.           greater1    : Eval_Comparison;
  1641.           leftbrack1: Eval_ArrayReference;
  1642.           less1    : Eval_Comparison;
  1643.           minus1    : if Expr^.Right = Nil then begin { Unary minus }
  1644.                 if Expr^.EType = RealType then
  1645.                     Eval_UnaryFloat(-60)
  1646.                 else
  1647.                     Eval_UnaryMath(op_NEG);
  1648.               end else begin
  1649.                 if Expr^.EType = RealType then
  1650.                     Eval_BinaryFloat(-72)
  1651.                 else
  1652.                     Eval_BinaryMath(op_SUB,True);
  1653.               end;
  1654.         else
  1655.         Writeln(OutFile, 'Did not do ', Ord(op));
  1656.         end;
  1657.     end;
  1658.     end else begin
  1659.     if op <= carat1 then begin
  1660.         case op of
  1661.           notequal1    : Eval_Comparison;
  1662.           notgreater1 : Eval_Comparison;
  1663.           notless1    : Eval_Comparison;
  1664.           period1    : Eval_RecordReference;
  1665.           plus1    : if Expr^.EType = RealType then
  1666.                   Eval_BinaryFloat(-66)
  1667.               else
  1668.                   Eval_BinaryMath(op_ADD,True);
  1669.           quote1    : begin
  1670.                   Out_Operation2(op_MOVE,4,ea_Literal,a7,
  1671.                             ea_Register,ToReg);
  1672.                   Out_Extension(Expr^.Value);
  1673.               end;
  1674.           carat1    : Eval_Dereference;
  1675.         else
  1676.         Writeln(OutFile, 'Did not do ', Ord(op));
  1677.         end;
  1678.     end else begin
  1679.         case op of
  1680.           at1    : EvalAddress(Expr^.Left, ToReg);
  1681.           realdiv1 : Eval_BinaryFloat(-84);
  1682.           int2real : Eval_UnaryFloat(-36);
  1683.           real2int : Eval_UnaryFloat(-30);
  1684.           short2long : begin
  1685.                 Evaluate(Expr^.Left, ToReg);
  1686.                 Out_Operation1(op_EXT,4,ea_Register,ToReg);
  1687.                end;
  1688.           byte2short : begin
  1689.                 Evaluate(Expr^.Left, ToReg);
  1690.                 Out_Operation2(op_AND,2,ea_Constant,a7,
  1691.                             ea_Register,ToReg);
  1692.                 Out_Extension(255);
  1693.                end;
  1694.           byte2long    : begin
  1695.                   Evaluate(Expr^.Left, ToReg);
  1696.                   ConstantOperation(op_AND, 4, $FF, ToReg);
  1697.               end;
  1698.           stanfunc1 : Eval_StandardFunction;
  1699.           field1    : Eval_FieldReference;
  1700.         else
  1701.         Writeln(OutFile, 'Did not do ', Ord(op));
  1702.         end;
  1703.     end;
  1704.     end;
  1705.     MarkRegister(ToReg);
  1706. end;
  1707.  
  1708. {
  1709. Procedure ReportTree(Expr : ExprPtr);
  1710. var
  1711.     ID : IDPtr;
  1712.     E2 : ExprPtr;
  1713.     TP : TypePtr;
  1714. begin
  1715.     Write(OutFile, '(');
  1716.     case Expr^.Kind of
  1717.     const1 : if Expr^.EType = RealType then
  1718.              Write(OutFile, Real(Expr^.Value))
  1719.          else
  1720.              Write(OutFile, Expr^.Value);
  1721.     and1,
  1722.     div1,
  1723.     or1,
  1724.     shl1,
  1725.     shr1,
  1726.     xor1,
  1727.     asterisk1,
  1728.     equal1,
  1729.     notequal1,
  1730.     greater1,
  1731.     less1,
  1732.     notgreater1,
  1733.     notless1,
  1734.     plus1,
  1735.     realdiv1,
  1736.     mod1 : begin
  1737.            ReportTree(Expr^.Left);
  1738.            case Expr^.Kind of
  1739.              and1 : Write(OutFile, ' and ');
  1740.              div1 : Write(OutFile, ' div ');
  1741.              mod1 : Write(OutFile, ' mod ');
  1742.              or1  : Write(OutFile, ' or ');
  1743.              shl1 : Write(OutFile, ' shl ');
  1744.              shr1 : Write(OutFile, ' shr ');
  1745.              xor1 : Write(OutFile, ' xor ');
  1746.              asterisk1 : Write(OutFile, ' * ');
  1747.              equal1 : Write(OutFile, ' = ');
  1748.              notequal1 : Write(OutFile, ' <> ');
  1749.              greater1 : write(OutFile, ' > ');
  1750.              less1 : Write(OutFile, ' < ');
  1751.              notgreater1 : Write(OutFile, ' <= ');
  1752.              notless1 : Write(OutFile, ' >= ');
  1753.              plus1 : Write(OutFile, ' + ');
  1754.              minus1 : Write(OutFile, ' - ');
  1755.              realdiv1 : Write(OutFile, ' / ');
  1756.            end;
  1757.            ReportTree(Expr^.Right);
  1758.         end;
  1759.     minus1: if Expr^.Right = Nil then begin
  1760.             Write(OutFile, '-');
  1761.             ReportTree(Expr^.Left);
  1762.         end else begin
  1763.             ReportTree(Expr^.Left);
  1764.             Write(OutFile, ' - ');
  1765.             ReportTree(Expr^.Right);
  1766.         end;
  1767.     func1 : begin
  1768.             ID := IDPtr(Expr^.Value);
  1769.             Write(OutFile, ID^.Name, '(');
  1770.             E2 := Expr^.Left;
  1771.             while E2 <> Nil do begin
  1772.             ReportTree(E2);
  1773.             Write(OutFile, ',');
  1774.             E2 := E2^.Next;
  1775.             end;
  1776.             Write(OutFile, ')');
  1777.         end;
  1778.     not1: begin
  1779.         write(OutFile, ' not ');
  1780.         ReportTree(Expr^.Left);
  1781.           end;
  1782.     type1: begin
  1783.         write(OutFile, 'type(');
  1784.         ReportTree(Expr^.Left);
  1785.         Write(OutFile, ')');
  1786.            end;
  1787.     var1 : begin
  1788.             ID := IDPtr(Expr^.Value);
  1789.             case ID^.Object of
  1790.               global,
  1791.               typed_const : Write(OutFile, ID^.Name);
  1792.               local,
  1793.               refarg,
  1794.               valarg : Write(OutFile, ID^.Offset, '(a5)');
  1795.             else
  1796.                 Write(OutFile, 'var(', Ord(ID^.Object), ')');
  1797.             end;
  1798.         end;
  1799.     leftbrack1 :
  1800.         begin
  1801.             ReportTree(Expr^.Left);
  1802.             Write(OutFile, '[');
  1803.             ReportTree(Expr^.Right);
  1804.             Write(OutFile, ']');
  1805.         end;
  1806.     period1    :
  1807.         begin
  1808.             ReportTree(Expr^.Left);
  1809.             Write(OutFile, '.', Expr^.Value);
  1810.         end;
  1811.     quote1    : Write(OutFile, '""');
  1812.     carat1    : begin
  1813.             ReportTree(Expr^.Left);
  1814.             Write(OutFile, '^');
  1815.           end;
  1816.     at1    : begin
  1817.              Write(OutFile, '@');
  1818.              ReportTree(Expr^.Left);
  1819.          end;
  1820.     int2real : begin
  1821.             write(OutFile, '_float(');
  1822.             ReportTree(Expr^.Left);
  1823.             write(OutFile, ')');
  1824.            end;
  1825.     real2int : begin
  1826.             Write(OutFile, '_trunc(');
  1827.             ReportTree(Expr^.Left);
  1828.             Write(OutFile, ')');
  1829.            end;
  1830.     short2long : begin
  1831.             Write(OutFile, 'short2long(');
  1832.             ReportTree(Expr^.Left);
  1833.             Write(OutFile, ')');
  1834.             end;
  1835.     byte2short : begin
  1836.             Write(OutFile, 'byte2short(');
  1837.             ReportTree(Expr^.Left);
  1838.             Write(OutFile, ')');
  1839.              end;
  1840.     byte2long : begin
  1841.             Write(OutFile, 'byte2long(');
  1842.             ReportTree(Expr^.Left);
  1843.             Write(OutFile, ')');
  1844.             end;
  1845.     stanfunc1 : begin
  1846.             Write(OutFile, 'standard', Expr^.Value, '(');
  1847.             ReportTRee(Expr^.Left);
  1848.             Write(OutFile, ')');
  1849.             end;
  1850.     field1    : Write(OutFile, 'withfield');
  1851.     else
  1852.     Writeln(OutFile, 'Did not report ', Ord(Expr^.Kind));
  1853.     end;
  1854.     Write(OutFile, ')');
  1855. end;
  1856. }
  1857.  
  1858. Function Expression : TypePtr;
  1859. var
  1860.     Expr : ExprPtr;
  1861.     TP   : TypePtr;
  1862. begin
  1863.     NextFreeExprNode := 0;
  1864.     ConstantExpression := False;
  1865.     Expr := ExpressionTree;
  1866.     Optimize(Expr);
  1867.     TP := Expr^.EType;
  1868.     FreeAllRegisters;
  1869. {    if DoReport then begin
  1870.     ReportTree(Expr);
  1871.     Writeln(OutFile);
  1872.     end; }
  1873.     Evaluate(Expr,d0);
  1874.     NextFreeExprNode := 0;
  1875.     Expression := Expr^.EType;
  1876. end;
  1877.  
  1878. Function ConExpr(VAR ConType : TypePtr) : Integer;
  1879. var
  1880.     Expr : ExprPtr;
  1881.     Result : Integer;
  1882. begin
  1883.     NextFreeExprNode := 0;
  1884.     ConstantExpression := True;
  1885.     Expr := ExpressionTree;
  1886.     ConstantExpression := False;
  1887.     Optimize(Expr);
  1888.     Result := Expr^.Value;
  1889.     if (Expr^.Kind = Const1) or (Expr^.Kind = Quote1) then begin
  1890.     ConType := Expr^.EType;
  1891.     NextFreeExprNode := 0;
  1892.     ConExpr := Result;
  1893.     end else begin
  1894.     NextFreeExprNode := 0;
  1895.     ConType := BadType;
  1896.     Error("Expecting a Constant Expression");
  1897.     ConExpr := 1;
  1898.     end;
  1899. end;
  1900.  
  1901.  
  1902. {
  1903.     Store the result of the expression Expr in the address Destination.
  1904.     The two expressions must pass TypeCheck, or this will not work at all.
  1905. }
  1906.  
  1907. Procedure StoreValue(Expr : ExprPtr; Destination : ExprPtr);
  1908. var
  1909.     STag : Byte;
  1910.     SameType : Boolean;
  1911.     Lab  : Integer;
  1912.     OtherReg : Regs;
  1913. begin
  1914.     STag := Destination^.EType^.Size;
  1915.     SameType := STag = Expr^.EType^.Size;
  1916.     if SimpleReference(Destination) then begin
  1917.     if Expr^.Kind = Const1 then begin
  1918.         OtherReg := TemporaryData;
  1919.         with Expr^ do begin
  1920.         if (OtherReg < a0) and (STag = 4) and (Value <= 127) and
  1921.             (Value >= -128) and (Value <> 0) then begin
  1922.             Out_Operation2(op_MOVEQ,3,ea_Constant,a7,
  1923.                         ea_Register,OtherReg);
  1924.             Out_Extension(Value);
  1925.             WriteSimpleDest(Destination,op_MOVE,4,
  1926.                         ea_Register,OtherReg,0,0);
  1927.         end else
  1928.             WriteSimpleDest(Destination,op_MOVE,STag,
  1929.                         ea_Constant,a7,Value,0);
  1930.         end;
  1931.     end else begin
  1932.         Evaluate(Expr,d0);
  1933.         WriteSimpleDest(Destination,op_MOVE,STag,ea_Register,d0,0,0);
  1934.     end;
  1935.     end else if SimpleType(Destination^.EType) then begin
  1936.     EvalAddress(Destination,a0);
  1937.     if Expr^.Kind = Const1 then begin
  1938.         Out_Operation2(op_MOVE,STag,ea_Constant,a7,ea_Indirect,a0);
  1939.         Out_Extension(Expr^.Value);
  1940.     end else if SimpleReference(Expr) and SameType then begin
  1941.         WriteSimpleSource(Expr,op_MOVE,STag,ea_Indirect,a0);
  1942.     end else begin
  1943.         Evaluate(Expr, d0);
  1944.         Out_Operation2(op_MOVE,STag,ea_Register,d0,ea_Indirect,a0);
  1945.     end;
  1946.     end else begin
  1947.     Evaluate(Expr,a0);
  1948.     EvalAddress(Destination,a1);
  1949.  
  1950.     Out_Operation2(op_MOVE,4,ea_Constant,a7,ea_Register,d1);
  1951.     Out_Extension(Pred(Destination^.EType^.Size));
  1952.  
  1953.     lab := GetLabel();
  1954.     Out_Operation1(op_LABEL,3,ea_Label,a7);
  1955.     Out_Extension(Lab);
  1956.     Out_Operation2(op_MOVE,1,ea_PostInc,a0,ea_PostInc,a1);
  1957.     Out_Operation2(op_DBRA,3,ea_Register,d1,ea_Label,a7);
  1958.     Out_Extension(Lab);
  1959.     end;
  1960. end;
  1961.  
  1962. Procedure Assignment;
  1963. {
  1964.     Not surprisingly, this routine handles assignments.
  1965. }
  1966. var
  1967.     Destination,
  1968.     Expr    : ExprPtr;
  1969. begin
  1970.     NextFreeExprNode := 0;
  1971.     FreeAllRegisters;
  1972.     Destination := GetReference;
  1973.     if not Match(becomes1) then begin
  1974.     Error("Expecting :=");
  1975.     return;
  1976.     end;
  1977.     Optimize(Destination);
  1978. {    if DoReport then begin
  1979.     ReportTree(Destination);
  1980.     writeln(OutFile);
  1981.     end; }
  1982.     Expr := ExpressionTree;
  1983.     if NumberType(Destination^.EType) then begin
  1984.     Expr := PromoteTypeA(Expr, Destination^.EType);
  1985.     if (Expr^.EType = RealType) and
  1986.         (Destination^.EType^.Object = ob_ordinal) then
  1987.         Expr := MakeNode(real2int, Expr, Nil, IntType, 0);
  1988.     end;
  1989. {    if DoReport then begin
  1990.     ReportTree(Expr);
  1991.     Writeln(OutFile);
  1992.     end; }
  1993.     Optimize(Expr);
  1994. {    if DoReport then begin
  1995.     ReportTree(Expr);
  1996.     Writeln(OutFile);
  1997.     end; }
  1998.  
  1999.     if TypeCheck(Destination^.EType, Expr^.EType) then
  2000.     StoreValue(Expr, Destination)
  2001.     else
  2002.     Error("Mismatched Types in Assignment");
  2003. end;
  2004.